package com.yami.shop.groupbuy.common.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.event.EsProductUpdateEvent;
import com.yami.shop.bean.event.SendMessageEvent;
import com.yami.shop.bean.model.OfflineHandleEvent;
import com.yami.shop.bean.model.ProdLang;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.param.NotifyTemplateParam;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.groupbuy.common.api.dto.ApiGroupActivityDto;
import com.yami.shop.groupbuy.common.api.dto.ApiGroupSkuDto;
import com.yami.shop.groupbuy.common.dao.GroupActivityMapper;
import com.yami.shop.groupbuy.common.dto.GroupActivityDto;
import com.yami.shop.groupbuy.common.enums.ActivityStatusEnum;
import com.yami.shop.groupbuy.common.enums.GroupActivityStatusEnum;
import com.yami.shop.groupbuy.common.model.GroupActivity;
import com.yami.shop.groupbuy.common.model.GroupSku;
import com.yami.shop.groupbuy.common.model.GroupTeam;
import com.yami.shop.groupbuy.common.service.GroupActivityService;
import com.yami.shop.groupbuy.common.service.GroupSkuService;
import com.yami.shop.groupbuy.common.service.GroupTeamService;
import com.yami.shop.manager.impl.LangManager;
import com.yami.shop.service.OfflineHandleEventService;
import com.yami.shop.service.ProductService;
import lombok.RequiredArgsConstructor;
import com.yami.shop.common.util.BeanUtil;
import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 拼团活动表
 *
 * @author LGH
 * @date 2019-08-27 17:55:57
 */
@Service
@RequiredArgsConstructor
public class GroupActivityServiceImpl extends ServiceImpl<GroupActivityMapper, GroupActivity> implements GroupActivityService {

    private final GroupActivityMapper groupActivityMapper;
    private final ProductService productService;
    private final GroupTeamService groupTeamService;
    private final GroupSkuService groupSkuService;

    private final OfflineHandleEventService offlineHandleEventService;
    private final ApplicationEventPublisher eventPublisher;
    private final LangManager langManager;

    @Override
    @Cacheable(cacheNames = "groupActivityInfo", key = "#prodId")
    public ApiGroupActivityDto getByProdId(Long prodId) {
        return groupActivityMapper.getByProdId(prodId);
    }

    @Override
    public IPage<GroupActivityDto> getGroupActivityPage(PageParam<GroupActivityDto> page, GroupActivityDto groupActivityDto) {
        IPage<GroupActivityDto> groupPage = groupActivityMapper.getGroupActivityPage(page, groupActivityDto);
        if (CollUtil.isEmpty(groupPage.getRecords())) {
            return groupPage;
        }
        List<Long> ids = groupPage.getRecords().stream().filter(item -> Objects.nonNull(item.getProdId())).map(GroupActivityDto::getProdId).collect(Collectors.toList());
        Map<Long, ProdLang> prodLangMap = langManager.getProdLangMap(ids);
        for (GroupActivityDto item : groupPage.getRecords()) {
            ProdLang prodLang = prodLangMap.get(item.getProdId());
            if (Objects.nonNull(prodLang)) {
                item.setProdName(prodLang.getProdName());
            }
        }
        return groupPage;
    }

    @Override
    public ApiGroupActivityDto getApiGroupActivityInfo(Long groupActivityId, Long prodId) {
        return groupActivityMapper.getApiGroupActivityInfo(groupActivityId, prodId);
    }

    @Override
    @CacheEvict(cacheNames = "groupActivityInfo", key = "#prodId")
    public void removeGroupActivityInfoCache(Long prodId) {
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invalidGroupActivity(Long groupActivityId) {
        GroupActivity groupActivity = getById(groupActivityId);
        // 获取未成团的团队
        List<GroupTeam> groupTeamList = groupTeamService.getNotGroupTeamsByActivityId(groupActivity.getGroupActivityId());

        // 处理未成团的拼团团队
        for (GroupTeam groupTeam : groupTeamList) {
            groupTeamService.updateNotGroupTeam(groupTeam);
        }

        // 更新活动状态
        groupActivityMapper.updateStatus(groupActivityId, GroupActivityStatusEnum.INVALID.value());

        // 商品类型恢复为普通商品
        productService.updateProductType(groupActivity.getProdId(), ProdType.PROD_TYPE_NORMAL.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditGroupActivity(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            // 更新拼团活动为未开启状态
            groupActivityMapper.updateStatus(offlineHandleEventAuditParam.getHandleId(), GroupActivityStatusEnum.DISABLE.value());
            GroupActivity groupActivity = getById(offlineHandleEventAuditParam.getHandleId());
            // 清除缓存
            GroupActivityServiceImpl groupActivityService = (GroupActivityServiceImpl) AopContext.currentProxy();
            groupActivityService.removeGroupActivityInfoCache(groupActivity.getProdId());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            groupActivityMapper.updateStatus(offlineHandleEventAuditParam.getHandleId(), GroupActivityStatusEnum.OFFLINE.getCode());
        }
        GroupActivity groupActivity = groupActivityMapper.selectById(offlineHandleEventAuditParam.getHandleId());
        //发送活动审核提醒给商家
        NotifyTemplateParam shopParam = new NotifyTemplateParam();
        shopParam.setShopId(groupActivity.getShopId());
        shopParam.setActivityId(groupActivity.getGroupActivityId());
        shopParam.setActivityName(groupActivity.getActivityName());
        shopParam.setSendType(SendType.ACTIVITY_AUDIT.getValue());
        eventPublisher.publishEvent(new SendMessageEvent(shopParam));
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offline(GroupActivity groupActivity, String offlineReason, Long sysUserId) {

        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setHandleId(groupActivity.getGroupActivityId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.GROUP_BUY.getValue());
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setShopId(groupActivity.getShopId());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);

        // 如果活动为开始的状态
        if (Objects.equals(groupActivity.getActivityStatus(), ActivityStatusEnum.UNDER_WAY.value())) {
            // 获取未成团的团队
            List<GroupTeam> groupTeamList = groupTeamService.getNotGroupTeamsByActivityId(groupActivity.getGroupActivityId());
            if (CollectionUtil.isNotEmpty(groupTeamList)) {
                for (GroupTeam groupTeam : groupTeamList) {
                    groupTeamService.updateNotGroupTeam(groupTeam);
                }

            }
        }
        // 更新活动状态为违规下架
        groupActivityMapper.updateStatus(groupActivity.getGroupActivityId(), GroupActivityStatusEnum.OFFLINE.value());

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditApply(Long eventId, Long activityId, String reapplyReason) {
        // 更新活动为待审核状态
        groupActivityMapper.updateStatus(activityId, GroupActivityStatusEnum.WAIT_AUDIT.value());

        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeProdTypeByGroupActivityIdList() {
        // 获取活动结束或团单结束未成团的拼团团队
        List<GroupActivity> groupActivitieList = list(new LambdaQueryWrapper<GroupActivity>()
                .lt(GroupActivity::getEndTime,new Date())
                .ne(GroupActivity::getStatus,GroupActivityStatusEnum.END.getCode())
                .ne(GroupActivity::getStatus, GroupActivityStatusEnum.DELETE.getCode())
        );
        invalidOrEndGroupActivity(groupActivitieList, GroupActivityStatusEnum.END.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleOfflineGroupProd(Long shopId, Long prodId) {
        // 失效团购活动
        GroupActivity groupActivity = groupActivityMapper.getUnInvalidGroupActivityByProdId(prodId);
        if (Objects.isNull(groupActivity)) {
            return;
        }
        groupActivityMapper.updateGroupActivityStatus(groupActivity.getGroupActivityId(), GroupActivityStatusEnum.INVALID.value());
        // 团购商品恢复为普通商品
        productService.updateProductType(prodId, ProdType.PROD_TYPE_NORMAL.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invalidGroupByShopId(Long shopId) {
        // 查询状态为进行中的团购活动
        List<GroupActivity> groupActivityList = groupActivityMapper.selectList(Wrappers.lambdaQuery(GroupActivity.class)
                .select(GroupActivity::getGroupActivityId, GroupActivity::getProdId, GroupActivity::getStatus)
                .eq(GroupActivity::getShopId, shopId)
                .eq(GroupActivity::getStatus, GroupActivityStatusEnum.ENABLE.getCode())
        );
        if (CollUtil.isEmpty(groupActivityList)) {
            return;
        }
        invalidOrEndGroupActivity(groupActivityList, GroupActivityStatusEnum.INVALID.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveGroupActivity(GroupActivity groupActivity) {
        // 判断是否是普通商品
        Product product = productService.getProductByProdId(groupActivity.getProdId());
        if (!Objects.equals(product.getProdType(), ProdType.PROD_TYPE_NORMAL.value())) {
            // 商品类型改变，请刷新页面后重试
            throw new YamiShopBindException("yami.prod.type.check");
        }

        // 默认为未启用状态
        groupActivity.setStatus(GroupActivityStatusEnum.DISABLE.value());

        groupActivity.setPrice(getGroupSpuPrice(groupActivity.getGroupSkuList()));
        // 保存团购信息
        save(groupActivity);

        // 保存sku
        batchSaveOrUpdateSku(groupActivity);

        // 更新商品为团购商品
        if (productService.updateProductToGroup(groupActivity.getGroupActivityId(), groupActivity.getProdId()) < 1) {
            // 商品类型改变，请刷新页面后重试
            throw new YamiShopBindException("yami.prod.type.check");
        }
        // 发送事件，清除掉如果是限时特惠中的可用商品
        //applicationContext.publishEvent(new RemoveDiscountProdByIdsEvent(Collections.singletonList(groupActivity.getProdId())));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGroupActivity(GroupActivity groupActivity) {
        groupActivity.setStatus(null);
        GroupActivity dbGroupActivity = getById(groupActivity.getGroupActivityId());
        if (!Objects.equals(dbGroupActivity.getShopId(), groupActivity.getShopId())) {
            throw new YamiShopBindException("yami.no.auth");
        }

        groupActivity.setPrice(getGroupSpuPrice(groupActivity.getGroupSkuList()));
        // 不更新的字段-预防非法修改
        groupActivity.setStatus(null);
        groupActivity.setProdId(null);
        groupActivityMapper.updateById(groupActivity);
        // 状态为未启用可以更新sku
        if (Objects.equals(GroupActivityStatusEnum.DISABLE.value(), dbGroupActivity.getStatus())) {
            batchSaveOrUpdateSku(groupActivity);
        }
    }

    @Override
    public GroupActivity getGroupActivityInfo(Long groupActivityId) {
        GroupActivity groupActivity = getById(groupActivityId);
        Product product = productService.getProductAndLang(groupActivity.getProdId());
        groupActivity.setProdPic(product.getPic());
        groupActivity.setProdName(product.getProdName());
        // 获取SKU列表
        List<ApiGroupSkuDto> groupSkuList = groupSkuService.getApiByGroupActivityIdAndProdId(groupActivity.getGroupActivityId());
        groupActivity.setGroupSkuList(groupSkuList);
        return groupActivity;
    }

    private void batchSaveOrUpdateSku(GroupActivity groupActivity) {
        List<GroupSku> groupSkus = BeanUtil.mapAsList(groupActivity.getGroupSkuList(), GroupSku.class);
        for (GroupSku sku : groupSkus) {
            sku.setGroupActivityId(groupActivity.getGroupActivityId());
            sku.setSellNum(null);
        }
        groupSkuService.saveOrUpdateBatch(groupSkus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateToDelete(GroupActivity groupActivity) {
        // 团购活动已经删除
        if (Objects.equals(groupActivity.getStatus(), GroupActivityStatusEnum.DELETE.value())) {
            return;
        }
        // 更新活动为已删除状态
        groupActivityMapper.updateToDelete(groupActivity.getGroupActivityId());
        // 活动还未失效或结束，需要更新商品类型为普通商品
        if (!Objects.equals(groupActivity.getStatus(), GroupActivityStatusEnum.END.value()) && !Objects.equals(groupActivity.getStatus(), GroupActivityStatusEnum.END.value())) {
            // 活动商品恢复为普通商品
            productService.updateProductType(groupActivity.getProdId(), ProdType.PROD_TYPE_NORMAL.value());
        }
    }

    /**
     * 获取sku中的最低价格
     * @param groupSkuList
     * @return
     */
    private Double getGroupSpuPrice(List<ApiGroupSkuDto> groupSkuList) {
        Double minPrice = null;
        for (ApiGroupSkuDto groupSku : groupSkuList) {
            if ((Objects.isNull(minPrice) || groupSku.getActPrice() < minPrice) && Objects.equals(groupSku.getStatus(), 1)) {
                minPrice = groupSku.getActPrice();
            }
        }
        return minPrice;
    }



    private void invalidOrEndGroupActivity(List<GroupActivity> groupActivityList, Integer status) {
        if (CollUtil.isEmpty(groupActivityList)) {
            return;
        }
        List<Long> groupActivityIds = Lists.newArrayList();
        List<Long> prodIds = Lists.newArrayList();
        for (GroupActivity groupActivity: groupActivityList){
            groupActivityIds.add(groupActivity.getGroupActivityId());
            if (!Objects.equals(groupActivity.getStatus(), GroupActivityStatusEnum.INVALID.getCode())) {
                prodIds.add(groupActivity.getProdId());
            }
        }

        // 拼团活动结束，商品恢复为普通商品
        productService.bathUpdateProductType(prodIds, ProdType.PROD_TYPE_NORMAL.value());
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, prodIds, EsOperationType.SAVE_BATCH));

        // 改变团购活动状态
        groupActivityMapper.batchUpdateGroupActivityStatus(groupActivityIds, status);
    }
}
